<template>

  <div class="layui-select"
       :class="{
      'has-content': hasContent,
      'has-clear': allowClear,
      'has-disabled': disabled,
    }"
  >
    <lay-dropdown
        ref="selectRef"
        :disabled="disabled"
        :contentClass="contentClass"
        :contentStyle="contentStyle"
        :autoFitWidth="autoFitWidth"
        :autoFitMinWidth="autoFitMinWidth"
        :teleportProps="teleportProps"
        @hide="handleHide"
        @show="openState = true"
    >
      <lay-input
          v-if="!multiple"
          :size="size"
          :disabled="disabled"
          readonly
          :modelValue="selectedValue[label]"
          :allow-clear="allowClear"
          :placeholder="_placeholder"
          class="layui-unselect"
          @clear.stop="handleClear"
      >
        <template v-if="slots.prepend" #prepend>
          <slot name="prepend"></slot>
        </template>
        <template v-if="slots.append" #append>
          <slot name="append"></slot>
        </template>
        <template #suffix>
          <lay-icon
              type="layui-icon-triangle-d"
              :class="{ triangle: openState }"
          ></lay-icon>
        </template>
      </lay-input>
      <lay-tag-input
          v-if="multiple"
          v-model="multipleValue"
          :allow-clear="allowClear"
          :placeholder="_placeholder"
          :collapseTagsTooltip="collapseTagsTooltip"
          :minCollapsedNum="minCollapsedNum"
          :disabled="disabled"
          :disabledInput="true"
          :size="size"
          :class="{ 'layui-unselect': true }"
          :style="{ width: '100%' }"
          @remove="handleRemove"
          @clear.stop="handleClear"
          @keyup.delete.capture.prevent.stop
          @keydown.enter.capture.prevent.stop
      >
        <template v-if="slots.prepend" #prepend>
          <slot name="prepend"></slot>
        </template>
        <template v-if="slots.append" #append>
          <slot name="append"></slot>
        </template>
        <template #suffix>
          <lay-icon
              type="layui-icon-triangle-d"
              :class="{ triangle: openState }"
          ></lay-icon>
        </template>
      </lay-tag-input>
      <template #content>

        <lay-card :style="{width: tableWidth+'px'}">
          <template v-if="slots.header" #title>
            <slot name="header" :form="formData" :submit="formSubmit"></slot>
          </template>
          <lay-table
              ref="tableRef"
              size="sm"
              :resize="true"
              :columns="tableColumns"
              :loading="loading"
              @row="handleSelectRow"
              :data-source="dataSource"
              v-model:selected-keys="selectedKeys">
            <template v-for="(item,index) in tableSlot" :key="index"
                      #[item]="{row, data, column, rowIndex, columnIndex}">
              <slot :name="item" :row="row" :data="data" :column="column" :rowIndex="rowIndex"
                    :columnIndex="columnIndex"></slot>
            </template>
          </lay-table>
          <template #footer v-if="pageOpen">
            <div class="table-select-page ">
              <lay-page size="sm" simple v-model="page.current" :total="page.total"></lay-page>
            </div>
          </template>
        </lay-card>
      </template>
    </lay-dropdown>
  </div>
</template>

<script lang="ts" setup>
import {StyleValue} from "vue";
import {DropdownTeleportProps} from "@layui/layui-vue/types/component/dropdown/interface";
import {isEmpty} from "es-toolkit/compat";

export interface SelectProps {
  name?: string;
  disabled?: boolean;
  placeholder?: string;
  searchPlaceholder?: string;
  modelValue?: any;
  multiple?: boolean;
  autoFitWidth?: boolean;
  autoFitMinWidth?: boolean;
  size?: "lg" | "md" | "sm" | "xs";
  collapseTagsTooltip?: boolean;
  minCollapsedNum?: number;
  allowClear?: boolean;
  contentClass?: string | Array<string | object> | object;
  contentStyle?: StyleValue;
  teleportProps?: DropdownTeleportProps;
  tableWidth?: number;
  id: string;
  label: string,
  columns: Array<any>;
  dataFun: Function;
  pageOpen?: boolean;
  limit?: number;
}

export interface SelectEmits {
  (e: "update:modelValue", value: string | number | object): void;

  (e: "change", value: string | number | object): void;

  (e: "search", value: string): void;

  (e: "remove-tag", value: string | number | object): void;

  (e: "clear"): void;
}

const props = withDefaults(defineProps<SelectProps>(), {
  collapseTagsTooltip: true,
  minCollapsedNum: 3,
  allowClear: false,
  autoFitWidth: true,
  autoFitMinWidth: true,
  modelValue: null,
  disabled: false,
  multiple: false,
  tableWidth: 500,
  size: "sm",
  pageOpen: true,
  limit: 10
});
const slots = useSlots();
const emits = defineEmits<SelectEmits>();
const loading = ref(false);
const tableColumns: Ref<Array<any>> = ref([])
const selectedKeys: Ref<Array<any>> = ref([]);
const openState: Ref<boolean> = ref(false);
const page = reactive({current: 1, limit: props.limit, total: 0});
const selectRef = ref();
const tableRef = ref();
const dataSource = ref([])
const formData = ref();

const selectedValue = computed({
  get() {
    return props.multiple && props.modelValue == null ? [] : props.modelValue;
  },
  set(value) {
    console.log(value)
    emits("update:modelValue", value);
    emits("change", value);
  },
});


const _placeholder = computed(() => {
  return hasContent.value ? "" : props.placeholder;
});
const tableSlot = computed(() => {
  const slots = []
  for (let column of props.columns) {
    slots.push(column.customSlot)
  }
  return slots;

})
const hasContent = computed(() => {
  if (Array.isArray(selectedValue.value)) {
    return selectedValue.value.length > 0;
  } else {
    return (
        selectedValue.value !== "" &&
        selectedValue.value !== undefined &&
        selectedValue.value !== null
    );
  }
});
const multipleValue = computed(() => {
  return selectedValue.value.map((item: any) => item[props.label])
});


async function getData() {
  loading.value = true;
  let res
  try {
    res = await props.dataFun({
      page: page,
      search: formData.value
    });
  } catch (e) {
    console.error(e)
  } finally {
    loading.value = false;
    dataSource.value = []
  }
  dataSource.value = res.data;
  page.total = res.total;
}

const handleHide = () => {
  openState.value = false;
};

const multiple = computed(() => {
  return props.multiple;
});

const handleClear = () => {
  selectRef.value.hide();
  if (multiple.value) {
    selectedKeys.value = [];
  } else {
    emits("update:modelValue", "")
  }

  emits("clear");
};

function handleSelectRow(row: any) {
  if (multiple.value) {
    return
  }
  selectedValue.value = {
    [props.label]: row[props.label],
    [props.id]: row[props.id]
  };
  selectRef.value.hide();
}

const handleRemove = (value: any) => {
  if (Array.isArray(selectedValue.value)) {
    selectedKeys.value = selectedValue.value.filter((item) => {
      return item[props.label] !== value
    }).map((item) => item[props.id]);
    emits("remove-tag", value);
  }
};

//插糟表单提交
function formSubmit() {
  page.current = 1
  getData()
}

watch(() => selectedKeys.value, (value) => {
  if (!tableRef.value) {
    return;
  }

  if (isEmpty(value)) {
    selectedValue.value = []
    return
  }
  const checkData = tableRef.value.getCheckData();
  const selectedValues: Array<any> = []
  for (let checkDatum of checkData) {
    selectedValues.push({
      [props.label]: checkDatum[props.label],
      [props.id]: checkDatum[props.id]
    })
  }
  selectedValue.value = selectedValues
})

onMounted(async () => {
  if (props.multiple) {
    tableColumns.value.push({title: "选项", width: "55px", type: "checkbox", fixed: "left"})
    selectedKeys.value = props.modelValue.map((item: any) => item[props.id])
  }
  tableColumns.value.push(...props.columns)
  await getData()
})
defineExpose({
  formSubmit
})
</script>

<style lang="less">
.table-select-page {
  display: flex;
  align-items: center;

  .layui-page-simple .layui-pager-jumper .layui-input[size=md] {
    width: 30px;
    padding: 0 4px;

    input {
      font-size: 12px;
    }
  }

  .layui-page {
    -moz-user-select: none; /* Firefox私有属性 */
    -webkit-user-select: none; /* WebKit内核私有属性 */
    -ms-user-select: none; /* IE私有属性(IE10及以后) */
    -khtml-user-select: none; /* KHTML内核私有属性 */
    -o-user-select: none; /* Opera私有属性 */
    user-select: none; /* CSS3属性 */

    span {
      font-size: 12px;
    }

    .layui-page-prev, .layui-page-next {
      height: auto;
      border: none;

      .layui-icon {
        font-size: 10px;
      }
    }
  }
}
</style>
